package com.buddy.learn.javasource._collection;

import lombok.Data;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * @author Buddy
 * @date 2021/5/10
 */
public class DelayQueueDemo {


    public static void main(String[] args) {
        BlockingQueue q = new DelayQueue();
        Product p = new Product(q);
        Consumer c = new Consumer(q);
        new Thread(c).start();
        new Thread(p).start();

    }

    private static class Product implements Runnable {
        private final BlockingQueue queue;

        Product(BlockingQueue queue) {
            this.queue = queue;
        }

        @Override
        public void run() {
            try {
                System.out.println(System.currentTimeMillis() + "begin put");
                long beginTime = System.currentTimeMillis();
                queue.put(new DelayedDTO(System.currentTimeMillis() + 2000L, beginTime));//延迟 2 秒执行
                queue.put(new DelayedDTO(System.currentTimeMillis() + 5000L, beginTime));//延迟 5 秒执行
                queue.put(new DelayedDTO(System.currentTimeMillis() + 1000L * 10, beginTime));//延迟 10 秒执行
                System.out.println(System.currentTimeMillis() + "end put");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    private static class Consumer implements Runnable {
        private final BlockingQueue queue;

        Consumer(BlockingQueue queue) {
            this.queue = queue;
        }

        @Override
        public void run() {
            try {
                System.out.println(System.currentTimeMillis() + "Consumer begin");
                ((DelayedDTO) queue.take()).run();
                ((DelayedDTO) queue.take()).run();
                ((DelayedDTO) queue.take()).run();
                System.out.println(System.currentTimeMillis() + "Consumer end");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    @Data
    private static class DelayedDTO implements Delayed {
        Long s;
        Long beginTime;

        DelayedDTO(long s, long beginTime) {
            this.s = s;
            this.beginTime = beginTime;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return unit.convert(s - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        }

        @Override
        public int compareTo(Delayed o) {
            return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
        }

        public void run() {
            System.out.println(System.currentTimeMillis() + "现在已经过了{" + (System.currentTimeMillis() - beginTime) / 1000 + "}秒钟");
        }
    }

}
